#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
高级网站访问器 - 使用Selenium模拟真实浏览器
专门针对CSDN等有严格反爬虫机制的网站
"""

import time
import random
import csv
import os
import subprocess
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, WebDriverException
import numpy as np

# ============= 配置区域（在这里修改参数） =================
CONFIG = {
    "URL": "https://blog.csdn.net/Zero_VPN/article/details/154238580?spm=1001.2014.3001.5501",
    "MAX_VISITS": 10,  # 访问次数
    "INTERVAL_MEAN": 60,  # 平均间隔时间（秒）
    "CSV_FILE": "visits_log_selenium.csv",
    "CHROME_DRIVER_PATH": "/usr/local/bin/chromedriver",  # Chrome驱动路径
}
# ========================================================

# 常见设备的 User-Agent 列表
USER_AGENTS = [
    # Desktop - Chrome
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    
    # Desktop - Firefox
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0",
    
    # Desktop - Safari
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
    
    # Mobile - iPhone
    "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
    
    # Mobile - Android
    "Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36",
]

def check_chrome_driver():
    """检查Chrome驱动是否可用"""
    try:
        result = subprocess.run(["which", "chromedriver"], capture_output=True, text=True)
        if result.returncode == 0:
            return result.stdout.strip()
        else:
            return None
    except:
        return None

def get_log_file_path():
    """获取日志文件路径"""
    script_dir = os.path.dirname(os.path.abspath(__file__))
    logs_dir = os.path.join(script_dir, "logs")
    if not os.path.exists(logs_dir):
        os.makedirs(logs_dir)
    return os.path.join(logs_dir, CONFIG["CSV_FILE"])

def now_iso():
    """返回当前时间的 ISO 格式字符串"""
    return datetime.utcnow().isoformat() + "Z"

def get_poisson_interval(mean):
    """使用泊松分布生成访问间隔时间，增加随机性"""
    interval = np.random.exponential(mean)
    # 增加随机波动，避免固定间隔
    random_factor = random.uniform(0.8, 1.5)
    return max(30.0, interval * random_factor)  # 最小间隔30秒

def get_random_user_agent():
    """随机选择一个 User-Agent"""
    return random.choice(USER_AGENTS)

def write_csv_header(csvfile):
    """写入 CSV 文件头"""
    with open(csvfile, "a", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        if f.tell() == 0:
            writer.writerow([
                "timestamp_utc", 
                "visit_number", 
                "url", 
                "user_agent",
                "status",
                "response_time",
                "page_title",
                "note"
            ])

def log_visit(visit_num, url, user_agent, status, response_time, page_title, note=""):
    """记录访问日志到 CSV"""
    log_file = get_log_file_path()
    with open(log_file, "a", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow([
            now_iso(),
            visit_num,
            url,
            user_agent,
            status,
            response_time,
            page_title,
            note
        ])

def setup_chrome_options(user_agent):
    """设置Chrome浏览器选项"""
    chrome_options = Options()
    
    # 基本配置
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    chrome_options.add_argument("--disable-blink-features=AutomationControlled")
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    
    # 设置User-Agent
    chrome_options.add_argument(f"--user-agent={user_agent}")
    
    # 窗口大小随机化
    width = random.randint(1200, 1920)
    height = random.randint(800, 1080)
    chrome_options.add_argument(f"--window-size={width},{height}")
    
    # 语言设置
    chrome_options.add_argument("--lang=zh-CN")
    
    # 禁用图片加载（可选，加快速度）
    # chrome_options.add_argument("--blink-settings=imagesEnabled=false")
    
    return chrome_options

def visit_with_selenium(url, user_agent, driver_path):
    """使用Selenium模拟真实浏览器访问"""
    driver = None
    try:
        # 设置浏览器选项
        chrome_options = setup_chrome_options(user_agent)
        
        # 启动浏览器
        driver = webdriver.Chrome(executable_path=driver_path, options=chrome_options)
        
        # 执行脚本隐藏自动化特征
        driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
        
        start_time = time.time()
        
        # 访问页面
        driver.get(url)
        
        # 等待页面加载
        WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.TAG_NAME, "body"))
        )
        
        # 模拟人类行为：随机滚动页面
        scroll_actions = random.randint(2, 5)
        for i in range(scroll_actions):
            scroll_height = random.randint(200, 800)
            driver.execute_script(f"window.scrollBy(0, {scroll_height});")
            time.sleep(random.uniform(0.5, 2.0))
        
        # 获取页面标题
        page_title = driver.title
        
        response_time = round(time.time() - start_time, 2)
        
        # 检查是否成功访问
        if "CSDN" in page_title or "博客" in page_title:
            return {
                'success': True,
                'status': '访问成功',
                'response_time': response_time,
                'page_title': page_title,
                'note': f'页面加载成功，标题: {page_title}'
            }
        else:
            return {
                'success': False,
                'status': '页面异常',
                'response_time': response_time,
                'page_title': page_title,
                'note': f'页面标题异常: {page_title}'
            }
        
    except TimeoutException:
        return {
            'success': False,
            'status': '超时错误',
            'response_time': 0,
            'page_title': '',
            'note': '页面加载超时'
        }
    except WebDriverException as e:
        return {
            'success': False,
            'status': '浏览器错误',
            'response_time': 0,
            'page_title': '',
            'note': f'浏览器异常: {str(e)}'
        }
    except Exception as e:
        return {
            'success': False,
            'status': '未知错误',
            'response_time': 0,
            'page_title': '',
            'note': f'未知错误: {str(e)}'
        }
    finally:
        if driver:
            driver.quit()

def main():
    """主函数"""
    print("=== 高级网站访问器启动 ===")
    
    # 检查Chrome驱动
    driver_path = check_chrome_driver()
    if not driver_path:
        print("❌ 未找到Chrome驱动，请先安装chromedriver")
        print("安装命令: sudo apt-get install chromium-chromedriver 或从官网下载")
        return
    
    print(f"✅ Chrome驱动路径: {driver_path}")
    
    # 初始化日志文件
    log_file = get_log_file_path()
    write_csv_header(log_file)
    print(f"✅ 日志文件: {log_file}")
    
    visit_count = 0
    max_visits = CONFIG["MAX_VISITS"] if CONFIG["MAX_VISITS"] > 0 else float('inf')
    
    print(f"🎯 目标URL: {CONFIG['URL']}")
    print(f"📊 计划访问次数: {max_visits if max_visits != float('inf') else '无限'}")
    print("⏰ 开始访问...\n")
    
    try:
        while visit_count < max_visits:
            visit_count += 1
            user_agent = get_random_user_agent()
            
            print(f"第 {visit_count} 次访问 - {datetime.now().strftime('%H:%M:%S')}")
            print(f"User-Agent: {user_agent[:50]}...")
            
            # 执行访问
            result = visit_with_selenium(CONFIG['URL'], user_agent, driver_path)
            
            # 记录结果
            log_visit(
                visit_count, 
                CONFIG['URL'], 
                user_agent,
                result['status'],
                result['response_time'],
                result['page_title'],
                result['note']
            )
            
            if result['success']:
                print(f"✅ {result['status']} - 耗时: {result['response_time']}秒")
                print(f"📄 页面标题: {result['page_title']}")
            else:
                print(f"❌ {result['status']} - {result['note']}")
            
            # 如果不是最后一次访问，等待间隔时间
            if visit_count < max_visits:
                interval = get_poisson_interval(CONFIG['INTERVAL_MEAN'])
                print(f"⏳ 等待 {interval:.1f} 秒后继续...\n")
                time.sleep(interval)
            else:
                print("\n🎉 所有访问完成！")
    
    except KeyboardInterrupt:
        print("\n⏹️ 用户中断程序")
    except Exception as e:
        print(f"\n💥 程序异常: {str(e)}")
    
    print(f"\n📊 总计访问次数: {visit_count}")
    print(f"📋 日志文件: {log_file}")

if __name__ == "__main__":
    main()